package com.yk.dataGatherer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yk.api.dataGatherer.dto.Fields;
import com.yk.api.dataGatherer.dto.SuperTableDTO;
import com.yk.api.dataGatherer.dto.TableDTO;
import com.yk.api.dataGatherer.dto.VariableDataCacheDTO;
import com.yk.api.system.dto.*;
import com.yk.api.system.model.DeviceFeignService;
import com.yk.common.core.constant.*;
import com.yk.common.core.domain.Result;
import com.yk.common.core.dto.DeviceUpdateDTO;
import com.yk.common.core.dto.GateWayUpdateDTO;
import com.yk.common.core.utils.DateUtils;
import com.yk.common.rabbitmq.constant.QueueConstants;
import com.yk.common.redis.service.RedisService;
import com.yk.dataGatherer.service.EmqWebHookService;
import com.yk.dataGatherer.service.TdEngineService;
import com.yk.dataGatherer.service.VariableDataService;
import com.yk.dataGatherer.websocket.WebSocketServer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlScript;
import org.apache.commons.jexl3.MapContext;
import org.apache.commons.jexl3.internal.Engine;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * EmqWebHookServiceImpl
 *
 * @author lmx
 * @date 2023/11/9 17:20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EmqWebHookServiceImpl implements EmqWebHookService {

    private final AmqpTemplate amqpTemplate;
    private final DeviceFeignService deviceFeignService;
    private final RedisService redisService;
    private final TdEngineService tdEngineService;
    @Value("${spring.datasource.dynamic.datasource.master.dbName}")
    private String masterDataBaseName;


    /**
     * 数据解析
     *
     * @param mqttStatus 操作类型
     * @param data       数据
     * @param gateway    网关
     */
    @Override
    public void fetchData(String mqttStatus, JSONObject data, GatewayDTO gateway, String clientId) {
        if (ObjectUtil.isNull(data) || Objects.isNull(gateway)) {
            return;
        }

        switch (mqttStatus) {
            case MqttConstants.ONLINE:
                Integer status = data.getInt(MqttConstants.ONLINE);
                if (Objects.isNull(status)) {
                    status = data.getInt(MqttConstants.OFFLINE);
                }
                String ccId = data.getStr(MqttConstants.CC_ID);
                try {
                    // 更新网关状态、流量卡号
                    amqpTemplate.convertAndSend(QueueConstants.GATEWAY_UPDATE, new GateWayUpdateDTO(gateway.getId(), status, ccId, clientId));
                } catch (Exception e) {
                    log.error("网关状态、流量卡号更新失败", e);
                    return;
                }
                break;
            case MqttConstants.DATA:
            case MqttConstants.VAR_READ_ACK:
                try {
                    // 客户端id更新
                    amqpTemplate.convertAndSend(QueueConstants.GATEWAY_UPDATE, new GateWayUpdateDTO(gateway.getId(), clientId));
                } catch (Exception e) {
                    log.error("网关状态、流量卡号更新失败", e);
                    return;
                }
                // 解析数据
                data(data, gateway);
                break;
            case MqttConstants.WRITE_ACK:
                String messageId = data.getStr(MqttConstants.MESSAGE_ID);
                String redisKey = CacheConstants.DEVICE_CONTROL_KEY + messageId;
                String address = redisService.getCacheObject(redisKey);
                if (CharSequenceUtil.isEmpty(address)) {
                    break;
                }
                String result = data.getStr(MqttConstants.RESULT);
                redisService.setCacheObject(redisKey, result, 30L, TimeUnit.SECONDS);
                break;
            default:
        }
    }

    /**
     * 提取设备信息
     *
     * @param data    数据
     * @param gateway 网关
     */
    private void data(JSONObject data, GatewayDTO gateway) {
        String devices = data.getStr(DeviceTypeConstants.DEVICES);
        if (StrUtil.isEmpty(devices)) {
            return;
        }
        // 循环处理设备
        JSONArray deviceArray = JSONUtil.parseArray(devices);
        for (int i = 0; i < deviceArray.size(); i++) {
            JSONObject devArr = deviceArray.getJSONObject(i);
            JSONObject devObj = JSONUtil.parseObj(devArr.getStr(DeviceTypeConstants.DEVICE_DATA));
            String deviceNum = devArr.getStr(DeviceTypeConstants.DEVICE_ID);
            Result<List<DeviceDTO>> listResult = deviceFeignService.selectByGateWayNumAndDeviceNum(gateway.getId(), deviceNum);
            if (!listResult.isSuccess()) {
                continue;
            }
            List<DeviceDTO> dtoList = listResult.getData();
            for (DeviceDTO dto : dtoList) {
                if (Objects.isNull(dto.getTemplateId())) {
                    continue;
                }
                devObj.set(DeviceTypeConstants.DEVICE_ID, dto.getId());
                devObj.set(DeviceTypeConstants.TEMP_ID, dto.getTemplateId());
                devObj.set(DeviceTypeConstants.DEVICE_NUM, deviceNum);
                devObj.set(DeviceTypeConstants.DEVICE_STATE, devArr.getStr(DeviceTypeConstants.DEVICE_STATE));
                realTimeData(devObj);
            }
        }
    }

    /**
     * 数据解析-历史数据入库-实时数据转发
     *
     * @param jsonObject 设备信息
     */
    public void realTimeData(JSONObject jsonObject) {
        // 设备ID
        String deviceId = jsonObject.getStr(DeviceTypeConstants.DEVICE_ID);
        // 设备编号
        String deviceNum = jsonObject.getStr(DeviceTypeConstants.DEVICE_NUM);
        // 模板ID
        String tempId = jsonObject.getStr(DeviceTypeConstants.TEMP_ID);
        // 更新设备状态
        updateDeviceState(jsonObject, deviceId);
        if (Objects.isNull(deviceId) || Objects.isNull(deviceNum) || Objects.isNull(tempId)) {
            return;
        }
        // 变量模板
        SuperTableDTO dto = redisService.getCacheObject(CacheConstants.SUPER_TABLE_FIELD_KEY + TdEngIneConstants.STABLE_PREFIX + tempId);
        if (Objects.isNull(dto) || CollUtil.isEmpty(dto.getPtFields())) {
            return;
        }
        // 当前设备的变量模版
        List<Fields> fields = dto.getPtFields();
        // 历史集合
        List<Fields> historyData = CollUtil.newArrayList();
        // 实时集合
        List<VariableDTO> realTimeData = CollUtil.newArrayList();
        Date date = new Date();
        // 普通变量
        fields.forEach(it -> parseData(it, jsonObject, deviceId, tempId, realTimeData, historyData, date));
        // 差值变量
        if (CollUtil.isNotEmpty(dto.getCzFields())){
            dto.getCzFields().forEach(it -> parseCzData(it, deviceId, tempId, realTimeData, historyData, date));
        }
        // 内部变量
        if (CollUtil.isNotEmpty(dto.getNbFields())){
            dto.getNbFields().forEach(it -> parseNbData(it, deviceId, tempId, realTimeData, historyData, date));
        }
        // 转发实时数据
        WebSocketServer.sendMessage(deviceId, JSONUtil.toJsonStr(realTimeData));
        redisService.setCacheObject(CacheConstants.DEVICE_REAL_DATA_KEY + deviceId, realTimeData);
        // 保存历史
        TableDTO tableDto = new TableDTO();
        List<Fields> tagsFieldValues = CollUtil.newArrayList(new Fields(deviceId), new Fields(deviceNum));
        tableDto.setTagsFieldValues(tagsFieldValues);
        tableDto.setSchemaFieldValues(historyData);
        tableDto.setTableName(TdEngIneConstants.TABLE_PREFIX + deviceId);
        tableDto.setSuperTableName(TdEngIneConstants.STABLE_PREFIX + tempId);
        try {
            amqpTemplate.convertAndSend(QueueConstants.DEVICE_HISTORY, tableDto);
        } catch (Exception e) {
            log.error("rabbitmq send error：{}", jsonObject);
        }
    }

    /**
     * 更新设备状态
     *
     * @param jsonObject 报文消息
     * @param deviceId   设备id
     */
    private void updateDeviceState(JSONObject jsonObject, String deviceId) {
        String deviceState = jsonObject.getStr(DeviceTypeConstants.DEVICE_STATE);
        if (StrUtil.isNotEmpty(deviceState)) {
            DeviceUpdateDTO deviceUpdateDTO = new DeviceUpdateDTO(Long.parseLong(deviceId), Integer.parseInt(deviceState));
            try {
                amqpTemplate.convertAndSend(QueueConstants.DEVICE_UPDATE_STATUS, deviceUpdateDTO);
            } catch (Exception e) {
                log.error("rabbitmq send error：{}", jsonObject);
            }
        }
    }

    /**
     * 设备数据解析入集合-报警提醒（普通变量）
     *
     * @param it                  表结构
     * @param jsonObject          设备信息
     * @param deviceId            设备ID
     * @param tempId              模版ID
     * @param allList             实时数据集合
     * @param historySchemaFields 历史存储数据集合
     */
    private void parseData(Fields it, JSONObject jsonObject, String deviceId, String tempId,
                           List<VariableDTO> allList, List<Fields> historySchemaFields, Date date) {
        // 变量地址
        String path = it.getFieldName();
        Object jsonValue = jsonObject.get(path);
        if (Objects.isNull(jsonValue)) {
            return;
        }
        // 变量值
        String value = jsonValue.toString();
        value = !NumberUtil.isNumber(value) ? MqttConstants.NAN : value;
        VariableDataService variableDataService;
        // 计算数据值 0-模拟量 1-开关量
        if (Objects.equals(NumberConstant.ZERO_STR, it.getType())) {
            variableDataService = new AnalogImpl();
        } else {
            variableDataService = new SwitchServiceImpl();
        }
        value = variableDataService.dealWith(value, it.getFormula(), it.getDecimal());
        // 实时
        VariableDTO variableDTO = new VariableDTO();
        variableDTO.setId(it.getVariableId());
        variableDTO.setName(it.getName());
        variableDTO.setType(it.getType());
        variableDTO.setDataType(NumberConstant.ZERO_STR);
        variableDTO.setUnit(it.getUnit());
        variableDTO.setAddress(path);
        variableDTO.setValue(value);
        variableDTO.setDeviceId(deviceId);
        variableDTO.setCreatedAt(date);
        allList.add(variableDTO);
        // 历史
        if (it.getStorage()) {
            it.setFieldValue(value);
            historySchemaFields.add(it);
        }
        // 报警
        alarmTemp(tempId, deviceId, it.getVariableId(), value);
        alarmDevice(deviceId, it.getVariableId(), value);
    }

    /**
     * 设备数据解析入集合-报警提醒（差值变量）
     *
     * @param it                  表结构
     * @param deviceId            设备ID
     * @param tempId              模版ID
     * @param allList             实时数据集合
     * @param historySchemaFields 历史存储数据集合
     */
    private void parseCzData(Fields it, String deviceId, String tempId, List<VariableDTO> allList,
                             List<Fields> historySchemaFields, Date date) {
        String type = it.getVariableDataType();
        if (StrUtil.isEmpty(type) || !NumberConstant.ONE_STR.equals(type)){
            return;
        }
        // 变量地址
        String path = it.getFieldName();
        // 引用变量
        Long parentId = it.getParentId();
        // 引用变量地址
        String parentAddress = it.getParentAddress();
        // 计算类型 0-周期 1-实时
        String computeType = it.getComputeType();
        String newValue = allList.stream()
                        .filter(real -> real.getId().equals(parentId))
                        .findFirst()
                        .map(VariableDTO::getValue)
                        .orElse(null);
        if (newValue == null) {
            return;
        }
        String cacheKey = deviceId + parentId;
        String oldValue = getOldValue(it, deviceId, date, parentAddress, computeType, newValue, cacheKey);
        if (oldValue == null){
            return;
        }
        // 上次的变量值
        oldValue = !NumberUtil.isNumber(oldValue) ? MqttConstants.NAN : oldValue;
        // 当次变量值
        newValue = !NumberUtil.isNumber(newValue) ? MqttConstants.NAN : newValue;
        try {
            // 计算差值
            BigDecimal subValue = new BigDecimal(newValue).subtract(new BigDecimal(oldValue));
            // 差值计算都是模拟量
            VariableDataService variableDataService = new AnalogImpl();
            String value = variableDataService.dealWith(subValue.toPlainString(), it.getFormula(), it.getDecimal());
            // 实时
            setVariableDTO(it, deviceId, allList, date, path, value);
            // 历史
            if (it.getStorage()) {
                it.setFieldValue(value);
                historySchemaFields.add(it);
            }
            // 报警
            alarmTemp(tempId, deviceId, it.getVariableId(), value);
            alarmDevice(deviceId, it.getVariableId(), value);
        }catch (NumberFormatException e){
            // 处理 BigDecimal 构造异常
            log.error("Failed to parse number", e.getMessage());
        }
    }

    /**
     * 获取上次变量值
     */
    private String getOldValue(Fields it, String deviceId, Date date, String parentAddress,
                               String computeType, String newValue, String cacheKey) {
        String oldValue;
        if (NumberConstant.ONE_STR.equals(computeType)) {
            Object jsonValue = redisService.get(CacheConstants.REAL_TIME_VARIABLE_DATA + cacheKey);
            if (Objects.nonNull(jsonValue)) {
                oldValue = jsonValue.toString();
            }else {
                oldValue = newValue;
            }
            redisService.set(CacheConstants.REAL_TIME_VARIABLE_DATA + cacheKey, newValue);
        } else {
            // 周期频率 0-日 1-周 2-月
            Date startTime;
            Date endTime;
            String cycleFrequency = it.getCycleFrequency();
            if (NumberConstant.ONE_STR.equals(cycleFrequency)) {
                startTime = DateUtils.getWeeklyStartTime(date);
                VariableDataCacheDTO dto = redisService
                        .getCacheObject(CacheConstants.WEEK_VARIABLE_DAY_DATA + cacheKey);
                if (Objects.nonNull(dto) && startTime.before(dto.getEndDate())){
                    oldValue = dto.getValue();
                }else {
                    endTime = DateUtils.getWeeklyEndTime(date);
                    oldValue = tdEngineService.selectLatestDataByTime(parentAddress, masterDataBaseName,
                            TdEngIneConstants.TABLE_PREFIX + deviceId, startTime, endTime);
                    if (StrUtil.isEmpty(oldValue)){
                        oldValue = newValue;
                    }
                    redisService.setCacheObject(CacheConstants.WEEK_VARIABLE_DAY_DATA + cacheKey,
                            new VariableDataCacheDTO(oldValue, startTime, endTime));
                }
            } else if (NumberConstant.TWO_STR.equals(cycleFrequency)) {
                startTime = DateUtils.getMonthStartTime(date);
                VariableDataCacheDTO dto = redisService
                        .getCacheObject(CacheConstants.MONTH_VARIABLE_DAY_DATA + cacheKey);
                if (Objects.nonNull(dto) && startTime.before(dto.getEndDate())){
                    oldValue = dto.getValue();
                }else {
                    endTime = DateUtils.getMonthEndTime(date);
                    oldValue = tdEngineService.selectLatestDataByTime(parentAddress, masterDataBaseName,
                            TdEngIneConstants.TABLE_PREFIX + deviceId, startTime, endTime);
                    if (StrUtil.isEmpty(oldValue)){
                        oldValue = newValue;
                    }
                    redisService.setCacheObject(CacheConstants.MONTH_VARIABLE_DAY_DATA + cacheKey,
                            new VariableDataCacheDTO(oldValue, startTime, endTime));
                }
            } else {
                startTime = DateUtils.getDayStartTime(date);
                VariableDataCacheDTO dto = redisService.getCacheObject(CacheConstants.DAY_VARIABLE_DATA + cacheKey);
                if (Objects.nonNull(dto) && startTime.before(dto.getEndDate())){
                    oldValue = dto.getValue();
                }else {
                    endTime = DateUtils.getDayEndTime(date);
                    oldValue = tdEngineService.selectLatestDataByTime(parentAddress, masterDataBaseName,
                            TdEngIneConstants.TABLE_PREFIX + deviceId, startTime, endTime);
                    if (StrUtil.isEmpty(oldValue)){
                        oldValue = newValue;
                    }
                    redisService.setCacheObject(CacheConstants.DAY_VARIABLE_DATA + cacheKey,
                            new VariableDataCacheDTO(oldValue, startTime, endTime));
                }
            }
        }
        if (StrUtil.isEmpty(oldValue) || StrUtil.isEmpty(newValue)){
            return null;
        }
        return oldValue;
    }

    /**
     * 设备数据解析入集合-报警提醒（内部变量）
     *
     * @param it                  表结构
     * @param deviceId            设备ID
     * @param tempId              模版ID
     * @param allList             实时数据集合
     * @param historySchemaFields 历史存储数据集合
     */
    private void parseNbData(Fields it, String deviceId, String tempId, List<VariableDTO> allList,
                             List<Fields> historySchemaFields, Date date) {
        String type = it.getVariableDataType();
        if (StrUtil.isEmpty(type) || !NumberConstant.TWO_STR.equals(type) || StrUtil.isEmpty(it.getFormula())){
            return;
        }
        // 变量地址
        String path = it.getFieldName();
        /**
         * 引用的内部变量 变量别名：变量地址
         * {
         *     "A": "Ia",
         *     "B": "Ib",
         *     "C": "Ic"
         * }
         */
        JSONObject interior = it.getInterior();
        // 小数位
        Integer decimal = it.getDecimal();
        if (Objects.isNull(decimal)){
            decimal = NumberConstant.TWO;
        }
        // 公式
        String formula = it.getFormula();
        if (Objects.isNull(interior)){
            return;
        }
        String value;
        try {
            JexlEngine engine = new Engine();
            JexlContext context = new MapContext();
            interior.forEach((k, v) -> {
                Optional<Fields> first = historySchemaFields.stream().filter(f -> f.getFieldName().equals(v)).findFirst();
                first.ifPresent(fields -> {
                    context.set(k, Double.parseDouble(fields.getFieldValue().toString()));
                });
            });
            JexlScript script = engine.createScript(formula);
            double result = Double.parseDouble(script.execute(context).toString());
            value = String.format("%." + decimal + "f", (result));
        } catch (Exception e) {
            log.error("公式解析异常：{}", e.getMessage());
            value = "NaN";
        }
        // 异常数据转换
        if ("-0".equals(value)){
            value = "0";
        }
        // 实时
        setVariableDTO(it, deviceId, allList, date, path, value);
        // 历史
        if (it.getStorage()) {
            it.setFieldValue(value);
            historySchemaFields.add(it);
        }
        // 报警
        alarmTemp(tempId, deviceId, it.getVariableId(), value);
        alarmDevice(deviceId, it.getVariableId(), value);
    }

    /**
     * 实时数据封装入集合
     */
    private void setVariableDTO(Fields it, String deviceId, List<VariableDTO> allList, Date date, String path, String value) {
        VariableDTO variableDTO = new VariableDTO();
        variableDTO.setName(it.getName());
        variableDTO.setType(it.getType());
        variableDTO.setDataType(NumberConstant.ONE_STR);
        variableDTO.setUnit(it.getUnit());
        variableDTO.setAddress(path);
        variableDTO.setValue(value);
        variableDTO.setDeviceId(deviceId);
        variableDTO.setCreatedAt(date);
        allList.add(variableDTO);
    }

    /**
     * 变量模版触发器
     *
     * @param tempId     模板id
     * @param variableId 变量id
     * @param value      变量值
     */
    private void alarmTemp(String tempId, String deviceId, Long variableId, String value) {
        AlarmDTO alarmDTO = new AlarmDTO();
        alarmDTO.setType(NumberConstant.ONE_STR);
        alarmDTO.setTargetId(Long.parseLong(tempId));
        alarmDTO.setVariableId(variableId);
        alarmDTO.setEnable(Boolean.TRUE);
        Result<List<AlarmDTO>> result = deviceFeignService.selectByAlarm(alarmDTO);
        if (!result.isSuccess() || Result.isCollNull(result)) {
            return;
        }
        List<AlarmDTO> dtoList = result.getData();
        dtoList.forEach(it -> alarm2Message(it, deviceId, variableId, value));
    }


    /**
     * 设备触发器
     *
     * @param deviceId   设备id
     * @param variableId 变量id
     * @param value      变量值
     */
    private void alarmDevice(String deviceId, Long variableId, String value) {
        AlarmDTO alarmDTO = new AlarmDTO();
        alarmDTO.setType(NumberConstant.ZERO_STR);
        alarmDTO.setTargetId(Long.parseLong(deviceId));
        alarmDTO.setVariableId(variableId);
        alarmDTO.setEnable(Boolean.TRUE);
        Result<List<AlarmDTO>> result = deviceFeignService.selectByAlarm(alarmDTO);
        if (!result.isSuccess() || Result.isCollNull(result)) {
            return;
        }
        List<AlarmDTO> dtoList = result.getData();
        dtoList.forEach(it -> alarm2Message(it, deviceId, variableId, value));
    }

    /**
     * 报警消息封装处理
     *
     * @param dto        报警规则DTO
     * @param deviceId   设备id
     * @param variableId 变量id
     * @param value      变量值
     */
    private void alarm2Message(AlarmDTO dto, String deviceId, Long variableId, String value) {
        ConditionDTO conditionDTO = dto.getRule();
        if (Objects.isNull(conditionDTO)) {
            return;
        }
        // 条件
        Integer condition = conditionDTO.getName();
        // 阈值一
        String thresholdOne = conditionDTO.getValueA();
        if (StrUtil.isEmpty(conditionDTO.getValueA())) {
            return;
        }
        // 阈值二
        String thresholdTwo = StrUtil.isEmpty(conditionDTO.getValueB()) ? "0" : conditionDTO.getValueB();
        // 变量名称
        String variableName = dto.getVariableName();
        // 是否推送
        String inform = dto.getInform();
        // 推送格式
        String informType = dto.getInformType();
        // 自定义报警消息
        String message = dto.getMessage();
        AlarmHistoryDTO alarmHistoryDTO = null;
        double dValue = Double.parseDouble(value);
        double dThresholdOne = Double.parseDouble(thresholdOne);
        double dThresholdTwo = Double.parseDouble(thresholdTwo);
        // 触发条件 0-大于A、1-小于A、2-等于A、3-大于A且小于B、4-小于A或者大于B、5-不等于
        switch (condition) {
            case 0:
                // 大于A
                message = StrUtil.isNotEmpty(message) ? message : variableName + "大于" + thresholdOne;
                if (dValue > dThresholdOne) {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.TRUE, message);
                } else {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.FALSE);
                }
                break;
            case 1:
                // 小于A
                message = StrUtil.isNotEmpty(message) ? message : variableName + "小于" + thresholdOne;
                if (dValue < dThresholdOne) {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.TRUE, message);
                } else {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.FALSE);
                }
                break;
            case 2:
                // 等于A
                message = StrUtil.isNotEmpty(message) ? message : variableName + "等于" + thresholdOne;
                if (value.equals(thresholdOne)) {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.TRUE, message);
                } else {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.FALSE);
                }
                break;
            case 3:
                // 大于A并且小于B
                message = StrUtil.isNotEmpty(message) ? message : variableName + "大于" + thresholdOne + "并且小于" + thresholdTwo;
                if (dValue > dThresholdOne && dValue < dThresholdTwo) {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.TRUE, message);
                } else {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.FALSE);
                }
                break;
            case 4:
                // 小于A或者小于B
                message = StrUtil.isNotEmpty(message) ? message : variableName + "小于" + thresholdOne + "或者小于" + thresholdTwo;
                boolean one = dValue < dThresholdOne;
                boolean tow = dValue < dThresholdTwo;
                if (one || tow) {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.TRUE, message);
                } else {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.FALSE);
                }
                break;
            case 5:
                // 5-不等于
                message = StrUtil.isNotEmpty(message) ? message : variableName + "不等于" + thresholdOne;
                if (!value.equals(thresholdOne)) {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.TRUE, message);
                } else {
                    alarmHistoryDTO = new AlarmHistoryDTO(Boolean.FALSE);
                }
                break;
            default:
                break;
        }

        if (Objects.nonNull(alarmHistoryDTO)) {
            alarmHistoryDTO.setAlarmId(dto.getId());
            alarmHistoryDTO.setDeviceId(Long.parseLong(deviceId));
            alarmHistoryDTO.setVariableId(variableId);
            // 是否恢复 false-正常
            if (alarmHistoryDTO.getAlarmState()) {
                alarmHistoryDTO.setAlarmValue(value);
            } else {
                alarmHistoryDTO.setRecoverValue(value);
            }
            // false 推送
            if (Boolean.FALSE.equals(Boolean.valueOf(inform))) {
                alarmHistoryDTO.setInformType(informType);
            }
            deviceFeignService.dealWithAlarmMessage(alarmHistoryDTO);
        }
    }
}
